import helper from '../../js/image-helper.js'
import handler from '../../js/moving-down-handler.js'

import Gesture from '../../../common/js/cls/Gesture.js'
import FlingAnimator from '../../../common/js/cls/FlingAnimator.js'
import ScaleAnimator from '../../../common/js/cls/ScaleAnimator.js'

const TRANSPARENT = '#00ffffff'

export default {
    data: {
        gesture: null,
        context: null,
        fling: null,
        scale: null,
        width: 0,
        height: 0,
        clearCanvas: false,
        trans: {
            desX: 0,
            desY: 0,
            transX: 0,
            transY: 0,
        },
        cond: {
            isShow: false,
            imageShow: true,
            opacity: 0,
        },
        image: {
            src: '',
            imgObj: null,
            imageWidth: 1,
            imageHeight: 1,
            initImageWidth: 1,
            initImageHeight: 1,
            currScale: 1,
            bg: TRANSPARENT
        },
        options: {
            duration: 200,
            easing: 'ease-in',
            fill: 'forwards'
        }
    },
    props: {
        background: {
            type: String,
            default: '#ffffffff'
        },
        maxScale: {
            type: Number,
            default: 4
        }
    },
    async onInit() {
        const that = this

        this.fling = new FlingAnimator()
        this.scale = new ScaleAnimator()

        this.gesture = new Gesture()
        this.gesture.setListener({
            onScroll: that.onScroll,
            onDoubleTap: that.onDoubleTap,
            onTap: that.hide,
            onLongPress() {},
            onFling: that.onFling
        })

        this.width = await this.$app.getScreenWidth()
        this.height = await this.$app.getScreenHeight()
    },
    onScroll(e, distanceX, distanceY, diffX, diffY, up) {
        const that = this
        if (handler.handleScroll(that, distanceX, distanceY, diffX, diffY, up)) return

        let transX = that.trans.transX
        let transY = that.trans.transY

        transX += diffX
        transY += diffY

        transX = that.limitX(transX)
        transY = that.limitY(transY)

        that.trans.transX = transX
        that.trans.transY = transY

        that.loadImage()
    },
    onDoubleTap(e) {
        const that = this

        const x = e.touches[0].globalX
        const y = e.touches[0].globalY

        const maxScale = parseInt(that.maxScale)

        let scale = that.image.currScale
        scale++
        if (scale > maxScale) scale = 1

        that.image.currScale = scale
        const reset = scale == 1

        const lastX = that.trans.transX
        const lastY = that.trans.transY

        const finalX = reset ? 0 : helper.calculateScaleTranslate(x, scale, that.image.initImageWidth, that.width, lastX)
        const finalY = reset ? 0 : helper.calculateScaleTranslate(y, scale, that.image.initImageHeight, that.height, lastY)

        that.scale.runScale(scale, lastX, lastY, finalX, finalY, (w, h, x, y) => {
            that.clearCanvas = reset

            that.image.imageWidth = w
            that.image.imageHeight = h

            that.trans.transX = x
            that.trans.transY = y

            that.loadImage()
        })
    },
    onFling(vx, vy, reached) {
        const that = this

        if (handler.handleFling(that, vx, vy) || !reached) return

        const maxX = helper.calulateMaxTranslate(that.image.imageWidth, that.width)
        const maxY = helper.calulateMaxTranslate(that.image.imageHeight, that.height)
        that.fling.runFling(that.trans.transX, that.trans.transY, vx * 2, vy * 2, -maxX, maxX, -maxY, maxY, (x, y) => {
            that.trans.transX = x
            that.trans.transY = y
            that.loadImage()
        })
    },
    loadImage() {
        if (!this.context) {
            const canvas = this.$element('canvas')
            this.context = canvas.getContext('2d')
        }

        if (!this.image.imgObj || this.image.imgObj.src != this.image.src) {
            this.image.imgObj = new Image()
            this.image.imgObj.src = this.image.src
        }

        const w = this.image.imageWidth
        const h = this.image.imageHeight

        const offsetX = helper.calculateDrawTranslate(w, this.width, this.trans.transX)
        const offsetY = helper.calculateDrawTranslate(h, this.height, this.trans.transY)

        if (this.clearCanvas) {
            this.context.clearRect(0, 0, this.width, this.height)
            this.clearCanvas = false
        }

        this.context.drawImage(this.image.imgObj, offsetX, offsetY, w, h)
    },
    down(e) {
        this.fling.forceFinished(true)
        this.gesture.onDown(e)
    },
    move(e) {
        this.gesture.onMove(e)
    },
    up(e) {
        this.gesture.onUp(e)
    },
    show(url, x, y, size) {
        this.cond.imageShow = true

        size = helper.getInitImageSize(size, this.width, this.height)
        this.image.imageWidth = this.image.initImageWidth = size.width
        this.image.imageHeight = this.image.initImageHeight = size.height

        this.scale.setSize(size.width, size.height)

        this.image.src = url
        this.cond.isShow = true

        this.trans.desX = x
        this.trans.desY = y

        setTimeout(() => {
            const bg = this.createAnimation(false, false)
            bg.play()

            const image = this.createAnimation(true, false)
            image.play()
            image.onfinish = () => {
                this.cond.imageShow = false
                this.cond.opacity = 1
                this.image.bg = this.background
                this.loadImage()
            }
        }, 30)
    },
    hide() {
        const bg = this.createAnimation(false, true)
        bg.play()

        const image = this.createAnimation(true, true)
        image.play()

        image.onfinish = () => {
            this.context = null
            this.bgContext = null
            this.cond.opacity = 0
            this.trans.transX = 0
            this.trans.transY = 0
            this.cond.isShow = false
            this.image.bg = TRANSPARENT
            this.image.currScale = 1
            this.scale.reset()
        }
    },
    limitX(transX, imageWidth) {
        return helper.restrictTranslate(transX, imageWidth || this.image.imageWidth, this.width)
    },
    limitY(transY, imageHeight) {
        return helper.restrictTranslate(transY, imageHeight || this.image.imageHeight, this.height)
    },
    createAnimation(image, reverse) {
        if (image) {
            return this.$element(reverse ? 'canvas' : 'image').animate(this.createImageFrames(reverse), this.options)
        } else {
            return this.$element('bg').animate(this.createBgFrames(reverse), this.options)
        }
    },
    createImageFrames(reverse) {
        const f1 = {
            transform: {
                translate: ((this.trans.desX - this.width / 2) + 'px ' +
                (this.trans.desY - this.height / 2) + 'px'),
                scale: '0.3'
            },
            opacity: 1
        }
        const f2 = {
            transform: {
                translate: '0px 0px',
                scale: '1'
            },
            opacity: 1
        }
        return this.createFrames(reverse, f1, f2)
    },
    createBgFrames(reverse) {
        const f1 = { backgroundColor: TRANSPARENT }
        const f2 = { backgroundColor: reverse ? this.image.bg : this.background }
        return this.createFrames(reverse, f1, f2)
    },
    createFrames(reverse, f1, f2) {
        if (reverse) {
            return [ f2, f1 ]
        }
        return [ f1, f2 ]
    }
}
